Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid using _PS_PRICE_COMPUTE_PRECISION_ #26824

Merged
merged 5 commits into from Mar 21, 2022

Conversation

mpaolino
Copy link
Contributor

@mpaolino mpaolino commented Dec 1, 2021

Questions Answers
Branch? 1.7.8.x
Description? PaymentModule::validateOrder is using the deprecated config constant
_PS_PRICE_COMPUTE_PRECISION_ to generate a string representation of the total amount paid with a payment module and comparing that to the cart total string representation calculated with Context::getContext()->getComputingPrecision(). This check will always fail when a currency with a decimal precision is different than the present _PS_PRICE_COMPUTE_PRECISION_ = 2 constant, hence the order will be placed in a payment error status and no log or further details will be displayed. This happens for example while using MercadoPago payment module v4.8.0 (official partner). Apparently PS_PRICE_COMPUTE_PRECISION was deprecated in 1.7.7.x but this core class still uses it. The proposed change substitutes the constant with the precision value obtained from the context, just like it is used in the rest of the source code. Also a log is added to register this error situation.
Type? bug fix
Category? CO
BC breaks? no
Deprecations? no
Fixed ticket? Fixes #26553
How to test? Create a currency with decimal values different than "2", make a purchase in the FO, order is created with status Configuration::get('PS_OS_ERROR') instead of a valid one. Full details in bug report.
Possible impacts? This is a core PaymentModule change so impact might be big, I'd check for all and any regressions regarding payments. There is still another place that _PS_PRICE_COMPUTE_PRECISION_ is in use in PaymentModule, this should be probably addressed in a different issue.

This change is Reviewable

@mpaolino mpaolino requested a review from a team as a code owner December 1, 2021 16:06
@prestonBot
Copy link
Collaborator

Hello @mpaolino!

This is your first pull request on the PrestaShop project. Thank you, and welcome to this Open Source community!

@prestonBot prestonBot added the Bug fix Type: Bug fix label Dec 1, 2021
Copy link
Contributor

@matks matks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR ! As I said in #26553 the PR seems good but we really need a list of clear steps to reproduce the bug, else QA team wont be able to reproduce the issue and verify it's now solved.

@matks matks added the Waiting for author Status: action required, waiting for author feedback label Dec 3, 2021
@prestonBot prestonBot added the develop Branch label Dec 6, 2021
@mpaolino
Copy link
Contributor Author

mpaolino commented Dec 6, 2021

Actually there is more than one bug in that single conditional line.The problem why QA could not reproduce it was probably they didn't made a purchase that was higher or equals to $1000.

The rationale behind that comparison is they are trying to avoid rounding errors, but:

  1. They are comparing with different number of decimal precision (number_format rounds the values).

  2. They are using the inequality operator to do the comparison, which will actually convert strings to numbers, and it will round numbers and incorrectly process commas in thousands separators. This achieves the complete opposite of what was intended.
    Notably, this situation yields wrong results if the purchase exceeds 1000, or if the purchase is lower than 1000 but the paid amount has any decimals.

php > var_dump(number_format(1000, 2));
string(8) "1,000.00"

php > var_dump(number_format(1000, 0));
string(5) "1,000"

php > var_dump(number_format(100, 2));
string(6) "100.00"

php > var_dump(number_format(100, 0));
string(3) "100"

This is how PHP prior to 8.0 does the comparison on number strings: https://www.php.net/manual/en/language.operators.comparison.php

So for example:

php > var_dump(number_format(1000, 2) != number_format(1000, 0));
bool(true)

php > var_dump(number_format(100, 2) != number_format(100, 0));
bool(false)

php > var_dump(number_format(100, 2) != number_format(100.10, 0));
bool(false)

There are a number of ways of doing this right but probably PHPs strcmp will work correctly independently of all combinations, I will update this if I have the time.

@mpaolino
Copy link
Contributor Author

mpaolino commented Dec 6, 2021

@matks done. Steps to reproduce in bug report.

@ocio87
Copy link

ocio87 commented Dec 7, 2021

Hello, I just tested the change in the PaymentModule.php file and it no longer throws a payment error with the bank transfer module in Colombia currency without decimals.

https://drive.google.com/file/d/1-6ESV_2R6voEnkq3kv4fIg5MkkT6kCRF/view?usp=sharing

image

Thanks,

sowbiba
sowbiba previously requested changes Dec 9, 2021
Copy link
Contributor

@sowbiba sowbiba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix seems good. Can you rebase 1.7.8.x and change the PR target ?

I can help if you need it

@sowbiba sowbiba linked an issue Dec 9, 2021 that may be closed by this pull request
2 tasks
Copy link
Contributor

@jolelievre jolelievre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mpaolino

classes/PaymentModule.php Outdated Show resolved Hide resolved
@mpaolino mpaolino changed the base branch from develop to 1.7.8.x December 9, 2021 21:57
@mpaolino mpaolino changed the base branch from 1.7.8.x to develop December 9, 2021 22:19
@mpaolino mpaolino requested a review from sowbiba December 9, 2021 22:21
mpaolino and others added 4 commits December 9, 2021 19:48
…mp to avoid conversion errors while doing comparisons
Change strcmp for strict inequality operator for amount string comparison

Co-authored-by: Jonathan Lelievre <jo.lelievre@gmail.com>
@mpaolino mpaolino changed the base branch from develop to 1.7.8.x December 9, 2021 22:54
@prestonBot prestonBot added the 1.7.8.x Branch label Dec 10, 2021
@Progi1984 Progi1984 added this to the 1.7.8.3 milestone Dec 13, 2021
@atomiix atomiix closed this Dec 16, 2021
@ocio87
Copy link

ocio87 commented Jan 17, 2022

Hello,

Adding what is indicated by @mpaolino.

Please remember that there is also evidence of the bug #26671 reported with the bank transfer module where multiple users have reported the same decimal problem.

Thanks,

@Guisardo
Copy link
Contributor

Hi @mpaolino , please notice that that the same constant is being used in another place of the same file:
https://github.com/PrestaShop/PrestaShop/blob/develop/classes/PaymentModule.php#L1160

Could you change that one too to avoid another PR?

@mpaolino
Copy link
Contributor Author

Hi @mpaolino , please notice that that the same constant is being used in another place of the same file:
https://github.com/PrestaShop/PrestaShop/blob/develop/classes/PaymentModule.php#L1160

Could you change that one too to avoid another PR?

Hi.

I already pointed that out in the initial PR report. This is a bug fix for a single reported bug, what your are asking here is that I complete the refactor of PaymentModule to completely remove the constant. Although I recognize there must be another underlying bug there, this is out of scope for this PR and I don't have the time to hunt for the triggering use cases. Feel free to provide the PR as it will require a different set of test instructions.

@sowbiba sowbiba added Blocked Status: The issue is blocked by another task and removed Waiting for author Status: action required, waiting for author feedback labels Jan 18, 2022
@mpaolino
Copy link
Contributor Author

mpaolino commented Jan 18, 2022

@sowbiba I assume there is something required from me since the issue is in "Waiting for author". Can you comment on that?

@mastudillot
Copy link

Any news to be able to mix the PR?

@atomiix atomiix added Waiting for QA Status: action required, waiting for test feedback and removed Blocked Status: The issue is blocked by another task labels Mar 3, 2022
@matks matks removed this from the 1.7.8.5 milestone Mar 18, 2022
@atomiix atomiix added this to the 1.7.8.6 milestone Mar 21, 2022
@florine2623 florine2623 removed the develop Branch label Mar 21, 2022
Copy link
Contributor

@sLorenzini sLorenzini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @mpaolino
Tested on 1.7.8.x branch.
PHP 7.2.21 version

Tested on cases below:

  • created order from BO with product > 1000 + < 1000
  • created order from FO with product > 1000 + < 1000
  • tested with custom currencies with decimal/without decimal
  • tested with custom currencies with modified exchange rate
  • tested with multiple payment modules
  • modified order statuses options

QA approved ✅

@sLorenzini sLorenzini added QA ✔️ Status: check done, code approved and removed Waiting for QA Status: action required, waiting for test feedback labels Mar 21, 2022
@Progi1984 Progi1984 merged commit a6e1caa into PrestaShop:1.7.8.x Mar 21, 2022
@Progi1984
Copy link
Contributor

Thanks @mpaolino

@mastudillot
Copy link

Thanks to everyone

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.7.8.x Branch Bug fix Type: Bug fix QA ✔️ Status: check done, code approved
Projects
None yet